﻿using System;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Windows.Forms;

namespace UserControls
{
    /// <summary>
    /// 自定义图像显示控件，支持缩放、平移、像素信息显示等功能
    /// 新增放大显示像素格功能
    /// </summary>
    public partial class UImage : Control
    {
        #region 事件|字段|属性

        #region 事件
        public event Action<PointF> ImagePixelPositionChanged;
        public event EventHandler DisplayedImageChanged;
        #endregion

        #region 字段
        // ==================== 图像显示参数 ====================
        private Image _displayedImage;                      // 当前显示的图像
        private Point _lastDragPosition;                    // 上次拖拽时的鼠标位置
        private PointF _imagePosition = new PointF(0, 0);   // 图像在控件中的显示位置
        private float _zoomFactor = 1.0f;                   // 当前缩放比例
        private const float MinimumZoom = 0.10f;            // 最小缩放比例
        private const float MaximumZoom = 20.0f;            // 最大缩放比例
        private const float ZoomIncrement = 0.2f;           // 缩放步长
        private bool _needsCentering = false;               // 标记是否需要居中图像

        // ==================== 背景网格参数 ====================
        private int _backgroundGridSize = 15;                           // 背景网格大小(像素)
        private Color _backgroundColor1 = Color.FromArgb(60, 60, 60);   // 背景颜色1
        private Color _backgroundColor2 = Color.FromArgb(80, 80, 80);   // 背景颜色2
        private PointF _currentImagePoint = new PointF(-1.0F, -1.0F);   // 当前鼠标指向的图像像素坐标

        // ==================== 信息显示参数 ====================
        private Font _infoDisplayFont = new Font("Arial", 12); // 信息显示字体
        private Color _infoTextColor = Color.DarkGray;         // 信息文本颜色
        private Color _infoBackgroundColor = Color.FromArgb(128, 0, 0, 0); // 信息背景颜色(半透明黑)

        // ==================== 缓存对象 ====================
        private SolidBrush _infoTextBrush;       // 信息文本画笔缓存
        private SolidBrush _infoBackgroundBrush; // 信息背景画笔缓存
        private SolidBrush _gridBrush1;          // 网格颜色1画笔缓存
        private SolidBrush _gridBrush2;          // 网格颜色2画笔缓存

        // ==================== 像素网格参数 ====================
        private bool _showPixelGrid = true;                     // 是否显示像素网格
        private float _pixelGridThreshold = 5.0f;               // 显示像素网格的缩放阈值
        private Color _pixelGridColor = Color.FromArgb(100, Color.White); // 像素网格颜色
        private Pen _pixelGridPen;                              // 像素网格画笔缓存
        #endregion

        #region 属性
        // ==================== 属性定义 ====================
        /// <summary>获取或设置控件显示的图像</summary>
        [Category("UserDefine")]
        [Description("控件显示的图像")]
        public Image DisplayedImage
        {
            get => _displayedImage;
            set
            {
                if (_displayedImage == value) return;
                _displayedImage = value;
                _needsCentering = true;
                CenterImage();
            }
        }

        /// <summary>获取当前鼠标指向的图像像素坐标</summary>
        [Category("UserDefine")]
        [Description("当前像素点")]
        [DefaultValue(typeof(double), "-1.0, -1.0")]
        public PointF CurrentImagePoint
        {
            get => _currentImagePoint;
            private set
            {
                if (_currentImagePoint == value) return;
                _currentImagePoint = value;
                Invalidate();
            }
        }

        /// <summary>获取或设置背景网格大小(像素)</summary>
        [Category("UserDefine")]
        [Description("控件网格大小")]
        [DefaultValue("15")]
        public int BackgroundGridSize
        {
            get => _backgroundGridSize;
            set
            {
                if (_backgroundGridSize == value) return;
                _backgroundGridSize = value;
                Invalidate();  // 网格大小改变需要重绘
            }
        }

        /// <summary>获取或设置背景颜色1</summary>
        [Category("UserDefine")]
        [Description("控件背景色1")]
        [DefaultValue("60, 60, 60")]
        public Color BackgroundColor1
        {
            get => _backgroundColor1;
            set
            {
                if (_backgroundColor1 == value) return;

                _backgroundColor1 = value;
                _gridBrush1 = new SolidBrush(value); // 创建新画笔
                Invalidate();
            }
        }

        /// <summary>获取或设置背景颜色2</summary>
        [Category("UserDefine")]
        [Description("控件背景色2")]
        [DefaultValue("80, 80, 80")]
        public Color BackgroundColor2
        {
            get => _backgroundColor2;
            set
            {
                if (_backgroundColor2 == value) return;

                _backgroundColor2 = value;
                _gridBrush2 = new SolidBrush(value);
                Invalidate();
            }
        }

        /// <summary>获取或设置信息显示字体</summary>
        [Category("UserDefine")]
        [Description("信息显示字体")]
        public Font InfoDisplayFont
        {
            get => _infoDisplayFont;
            set
            {
                if (_infoDisplayFont == value) return;
                _infoDisplayFont = value;     // 设置新字体
                Invalidate();
            }
        }

        /// <summary>获取或设置信息文本颜色</summary>
        [Category("UserDefine")]
        [Description("信息显示颜色")]
        [DefaultValue(typeof(Color), "DarkGray")]
        public Color InfoTextColor
        {
            get => _infoTextColor;
            set
            {
                if (_infoTextColor == value) return;

                _infoTextColor = value;
                _infoTextBrush = new SolidBrush(value);
                Invalidate();
            }
        }

        /// <summary>获取或设置信息背景颜色</summary>
        [Category("UserDefine")]
        [Description("信息背景颜色")]
        [DefaultValue(typeof(Color), "128, 0, 0, 0")]
        public Color InfoBackgroundColor
        {
            get => _infoBackgroundColor;
            set
            {
                if (_infoBackgroundColor == value) return;
                _infoBackgroundColor = value;
                _infoBackgroundBrush = new SolidBrush(value);
                Invalidate();
            }
        }

        /// <summary>获取或设置是否显示像素网格</summary>
        [Category("UserDefine")]
        [Description("是否显示像素网格")]
        [DefaultValue(true)]
        public bool ShowPixelGrid
        {
            get => _showPixelGrid;
            set
            {
                if (_showPixelGrid == value) return;
                _showPixelGrid = value;
                Invalidate();
            }
        }

        /// <summary>获取或设置显示像素网格的缩放阈值</summary>
        [Category("UserDefine")]
        [Description("显示像素网格的缩放阈值")]
        [DefaultValue(5.0f)]
        public float PixelGridThreshold
        {
            get => _pixelGridThreshold;
            set
            {
                if (_pixelGridThreshold == value) return;
                _pixelGridThreshold = value;
                Invalidate();
            }
        }

        /// <summary>获取或设置像素网格颜色</summary>
        [Category("UserDefine")]
        [Description("像素网格颜色")]
        [DefaultValue(typeof(Color), "100, 255, 255, 255")]
        public Color PixelGridColor
        {
            get => _pixelGridColor;
            set
            {
                if (_pixelGridColor == value) return;
                _pixelGridColor = value;
                _pixelGridPen = new Pen(value);
                Invalidate();
            }
        }
        #endregion

        #endregion

        #region 构造函数
        public UImage()
        {
            DoubleBuffered = true;  // 启用双缓冲减少闪烁
            this.DoubleBuffered = true;
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
                 ControlStyles.UserPaint |
                 ControlStyles.AllPaintingInWmPaint |
                 ControlStyles.ResizeRedraw, true);
            this.UpdateStyles();
            // 初始化画笔缓存
            _gridBrush1 = new SolidBrush(_backgroundColor1);
            _gridBrush2 = new SolidBrush(_backgroundColor2);
            _infoTextBrush = new SolidBrush(_infoTextColor);
            _infoBackgroundBrush = new SolidBrush(_infoBackgroundColor);
            _pixelGridPen = new Pen(_pixelGridColor);
        }
        #endregion

        #region 图像处理方法
        // ==================== 私有方法 ====================
        /// <summary>将屏幕坐标转换为图像坐标</summary>
        private PointF ScreenToImageCoordinates(Point screenPoint)
        {
            return new PointF(
                (screenPoint.X - _imagePosition.X) / _zoomFactor,
                (screenPoint.Y - _imagePosition.Y) / _zoomFactor);
        }
        /// <summary>获取图像在控件中的显示区域</summary>
        private RectangleF GetImageDisplayRectangle()
        {
            if (_displayedImage == null)
                return RectangleF.Empty;

            return new RectangleF(
                _imagePosition.X,
                _imagePosition.Y,
                _displayedImage.Width * _zoomFactor,
                _displayedImage.Height * _zoomFactor);
        }
        /// <summary>居中显示图像，自动计算合适的缩放比例</summary>
        private void CenterImage()
        {
            if (_displayedImage == null) return;

            // 获取图像和控件的尺寸
            int imageWidth = _displayedImage.Width;
            int imageHeight = _displayedImage.Height;

            // 判断图像是否大于控件显示区域
            bool isImageLarger = imageWidth > Width || imageHeight > Height;

            // 计算缩放比例：图像大于控件时自适应，否则使用原始尺寸
            _zoomFactor = isImageLarger ? Math.Min((float)Width / imageWidth, (float)Height / imageHeight) : 1.0f;

            // 限制缩放比例在有效范围内
            _zoomFactor = Math.Max(MinimumZoom, Math.Min(MaximumZoom, _zoomFactor));

            // 计算缩放后的图像显示尺寸
            float displayWidth = imageWidth * _zoomFactor;
            float displayHeight = imageHeight * _zoomFactor;

            // 计算居中位置
            _imagePosition = new PointF((Width - displayWidth) / 2,(Height - displayHeight) / 2 );
            _needsCentering = false;  // 清除居中标记
            Invalidate();  // 请求重绘
        }
        /// <summary>重置图像显示(缩放比例恢复为1.0并居中)</summary>
        public void ResetImageDisplay()
        {
            _zoomFactor = 1.0f;  // 重置缩放比例
            CenterImage();       // 居中显示
        }
        /// <summary>获取指定图像坐标处的像素颜色</summary>
        private Color GetPixelColorAt(PointF imagePoint)
        {
            // 检查坐标是否有效
            if (_displayedImage == null ||
                imagePoint.X < 0 || imagePoint.X >= _displayedImage.Width ||
                imagePoint.Y < 0 || imagePoint.Y >= _displayedImage.Height)
            {
                return Color.Empty;  // 无效坐标返回空颜色
            }
            try
            {
                // 如果是Bitmap直接获取像素
                if (_displayedImage is Bitmap bitmap)
                {
                    return bitmap.GetPixel((int)imagePoint.X, (int)imagePoint.Y);
                }
                // 对于其他Image类型，创建临时Bitmap获取像素
                using (Bitmap tempBitmap = new Bitmap(_displayedImage))
                {
                    return tempBitmap.GetPixel((int)imagePoint.X, (int)imagePoint.Y);
                }
            }
            catch
            {
                return Color.Empty;  // 出错返回空颜色
            }
        }
        /// <summary>绘制背景网格</summary>
        private void DrawBackgroundGrid(PaintEventArgs e)
        {
            Rectangle clipRect = e.ClipRectangle;  // 获取需要重绘的区域
            // 计算网格起始位置(对齐到网格边界)
            int startX = (int)(clipRect.Left / _backgroundGridSize) * _backgroundGridSize;
            int startY = (int)(clipRect.Top / _backgroundGridSize) * _backgroundGridSize;
            // 遍历所有需要绘制的网格单元格
            for (int y = startY; y < clipRect.Bottom; y += _backgroundGridSize)
            {
                for (int x = startX; x < clipRect.Right; x += _backgroundGridSize)
                {
                    // 交替使用两种颜色绘制网格
                    bool isAlternateCell = ((x / _backgroundGridSize) + (y / _backgroundGridSize)) % 2 == 0;
                    var brush = isAlternateCell ? _gridBrush1 : _gridBrush2;
                    e.Graphics.FillRectangle(brush, x, y, _backgroundGridSize, _backgroundGridSize);
                }
            }
        }
        /// <summary>绘制像素网格</summary>
        private void DrawPixelGrid(PaintEventArgs e)
        {
            if (_displayedImage == null || !_showPixelGrid || _zoomFactor < _pixelGridThreshold)
                return;

            RectangleF imageRect = GetImageDisplayRectangle();

            // 计算可见的图像区域
            int startX = Math.Max(0, (int)((-imageRect.X) / (_zoomFactor * _displayedImage.Width) * _displayedImage.Width));
            int startY = Math.Max(0, (int)((-imageRect.Y) / (_zoomFactor * _displayedImage.Height) * _displayedImage.Height));
            int endX = Math.Min(_displayedImage.Width, (int)((Width - imageRect.X) / (_zoomFactor * _displayedImage.Width) * _displayedImage.Width) + 1);
            int endY = Math.Min(_displayedImage.Height, (int)((Height - imageRect.Y) / (_zoomFactor * _displayedImage.Height) * _displayedImage.Height) + 1);

            // 绘制垂直线
            for (int x = startX; x <= endX; x++)
            {
                float screenX = imageRect.X + x * _zoomFactor;
                e.Graphics.DrawLine(_pixelGridPen, screenX, imageRect.Top, screenX, imageRect.Bottom);
            }

            // 绘制水平线
            for (int y = startY; y <= endY; y++)
            {
                float screenY = imageRect.Y + y * _zoomFactor;
                e.Graphics.DrawLine(_pixelGridPen, imageRect.Left, screenY, imageRect.Right, screenY);
            }
        }
        #endregion

        #region 重写事件方法
        /// <summary>绘制控件</summary>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            // 设置高质量图像绘制参数
            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            // 绘制背景网格
            DrawBackgroundGrid(e);
            if (_displayedImage == null)
                return;
            // 绘制图像
            RectangleF imageRect = GetImageDisplayRectangle();
            e.Graphics.DrawImage(_displayedImage, imageRect);
            DrawPixelGrid(e);
            // ===== 准备显示信息 =====
            // 图像尺寸信息
            string imageWidth = _displayedImage.Width.ToString("D4");
            string imageHeight = _displayedImage.Height.ToString("D4");
            string imageDimensions = $"W*H    {imageWidth}*{imageHeight}  ";
            // 坐标信息
            string xCoord = _currentImagePoint.X >= 0 ? _currentImagePoint.X.ToString("0000.0") : "N/A  ";
            string yCoord = _currentImagePoint.Y >= 0 ? _currentImagePoint.Y.ToString("0000.0") : "N/A  ";
            string coordinateInfo = $"  X: {xCoord}, Y: {yCoord}  ";
            // 颜色信息
            Color pixelColor = GetPixelColorAt(_currentImagePoint);
            string rValue = pixelColor != Color.Empty ? pixelColor.R.ToString("D3") : "N/A";
            string gValue = pixelColor != Color.Empty ? pixelColor.G.ToString("D3") : "N/A";
            string bValue = pixelColor != Color.Empty ? pixelColor.B.ToString("D3") : "N/A";
            string colorInfo = $"  R: {rValue}  G: {gValue}  B: {bValue}";
            // 组合显示文本
            string displayText = $"{imageDimensions}|{coordinateInfo}|{colorInfo}";
            // 计算信息显示区域大小(使用最大可能文本来确定背景大小)
            string maxWidthText = "W*H    9999 * 9999  |  X: 9999.9, Y: 9999.9  |  R: 255  G: 255  B: 255";
            SizeF maxTextSize = e.Graphics.MeasureString(maxWidthText, _infoDisplayFont);
            // 计算文本位置(右下角，留出边距)
            float textX = ClientSize.Width - maxTextSize.Width - 10;
            float textY = ClientSize.Height - maxTextSize.Height - 10;
            // 确保文本不会超出控件边界
            textX = Math.Max(10, textX);
            textY = Math.Max(10, textY);
            // 绘制文本背景(半透明矩形)
            e.Graphics.FillRectangle(_infoBackgroundBrush, textX, textY,Width,30);
            // 绘制文本
            e.Graphics.DrawString(displayText, _infoDisplayFont, _infoTextBrush, textX, textY);
        }
        /// <summary>控件大小改变时调用</summary>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            CenterImage();   // 保持图像居中
        }
        /// <summary>双击控件时调用</summary>
        protected override void OnDoubleClick(EventArgs e)
        {
            base.OnDoubleClick(e);
            ResetImageDisplay();  // 双击重置图像显示
        }
        /// <summary>鼠标按下时调用</summary>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Button == MouseButtons.Left && _displayedImage != null)
            {
                _lastDragPosition = e.Location;  // 记录拖拽起始位置
                Cursor = Cursors.Hand;           // 改变鼠标指针形状
            }
        }
        /// <summary>鼠标释放时调用</summary>
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            Cursor = Cursors.Default;  // 恢复默认鼠标指针
        }
        /// <summary>鼠标移动时调用</summary>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (_displayedImage != null)
            {
                // 更新当前鼠标指向的图像坐标
                RectangleF imageRect = GetImageDisplayRectangle();
                CurrentImagePoint = imageRect.Contains(e.Location)
                    ? ScreenToImageCoordinates(e.Location)
                    : new PointF(-1, -1);
            }

            // 处理鼠标拖拽平移图像
            if (e.Button == MouseButtons.Left && _displayedImage != null)
            {
                _imagePosition.X += (e.X - _lastDragPosition.X);
                _imagePosition.Y += (e.Y - _lastDragPosition.Y);
                _lastDragPosition = e.Location;
                Invalidate();  // 请求重绘
            }
        }
        /// <summary>鼠标滚轮滚动时调用</summary>
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
            if (_displayedImage == null)
                return;

            // 获取缩放前的鼠标位置(图像坐标)
            PointF mouseImagePosition = ScreenToImageCoordinates(e.Location);

            // 调整缩放比例(根据滚轮方向)
            _zoomFactor += (e.Delta > 0 ? ZoomIncrement : -ZoomIncrement);
            // 限制缩放比例在有效范围内
            _zoomFactor = Math.Max(MinimumZoom, Math.Min(MaximumZoom, _zoomFactor));

            // 计算缩放后的鼠标位置(屏幕坐标)
            PointF mouseScreenPositionAfterZoom = new PointF(
                mouseImagePosition.X * _zoomFactor + _imagePosition.X,
                mouseImagePosition.Y * _zoomFactor + _imagePosition.Y);

            // 调整图像位置，使鼠标指向的图像点保持不动
            _imagePosition.X += (e.Location.X - mouseScreenPositionAfterZoom.X);
            _imagePosition.Y += (e.Location.Y - mouseScreenPositionAfterZoom.Y);

            Invalidate();  // 请求重绘
        }
        #endregion
    }
}
